home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-M68K / STRING.H < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-17  |  11.8 KB  |  546 lines

  1. #ifndef _M68K_STRING_H_
  2. #define _M68K_STRING_H_
  3.  
  4. #include <asm/setup.h>
  5. #include <asm/page.h>
  6.  
  7. #define __HAVE_ARCH_STRCPY
  8. extern inline char * strcpy(char * dest,const char *src)
  9. {
  10.   char *xdest = dest;
  11.  
  12.   __asm__ __volatile__
  13.        ("1:\tmoveb %1@+,%0@+\n\t"
  14.         "jne 1b"
  15.     : "=a" (dest), "=a" (src)
  16.         : "0" (dest), "1" (src) : "memory");
  17.   return xdest;
  18. }
  19.  
  20. #define __HAVE_ARCH_STRNCPY
  21. extern inline char * strncpy(char *dest, const char *src, size_t n)
  22. {
  23.   char *xdest = dest;
  24.  
  25.   if (n == 0)
  26.     return xdest;
  27.  
  28.   __asm__ __volatile__
  29.        ("1:\tmoveb %1@+,%0@+\n\t"
  30.     "jeq 2f\n\t"
  31.         "subql #1,%2\n\t"
  32.         "jne 1b\n\t"
  33.         "2:"
  34.         : "=a" (dest), "=a" (src), "=d" (n)
  35.         : "0" (dest), "1" (src), "2" (n)
  36.         : "memory");
  37.   return xdest;
  38. }
  39.  
  40. #define __HAVE_ARCH_STRCAT
  41. extern inline char * strcat(char * dest, const char * src)
  42. {
  43.     char *tmp = dest;
  44.  
  45.     while (*dest)
  46.         dest++;
  47.     while ((*dest++ = *src++))
  48.         ;
  49.  
  50.     return tmp;
  51. }
  52.  
  53. #define __HAVE_ARCH_STRNCAT
  54. extern inline char * strncat(char *dest, const char *src, size_t count)
  55. {
  56.     char *tmp = dest;
  57.  
  58.     if (count) {
  59.         while (*dest)
  60.             dest++;
  61.         while ((*dest++ = *src++)) {
  62.             if (--count == 0) {
  63.                 *dest++='\0';
  64.                 break;
  65.             }
  66.         }
  67.     }
  68.  
  69.     return tmp;
  70. }
  71.  
  72. #define __HAVE_ARCH_STRCHR
  73. extern inline char * strchr(const char * s, int c)
  74. {
  75.   const char ch = c;
  76.   
  77.   for(; *s != ch; ++s)
  78.     if (*s == '\0')
  79.       return( NULL );
  80.   return( (char *) s);
  81. }
  82.  
  83. #define __HAVE_ARCH_STRPBRK
  84. extern inline char * strpbrk(const char * cs,const char * ct)
  85. {
  86.   const char *sc1,*sc2;
  87.   
  88.   for( sc1 = cs; *sc1 != '\0'; ++sc1)
  89.     for( sc2 = ct; *sc2 != '\0'; ++sc2)
  90.       if (*sc1 == *sc2)
  91.     return((char *) sc1);
  92.   return( NULL );
  93. }
  94.  
  95. #define __HAVE_ARCH_STRSPN
  96. extern inline size_t strspn(const char *s, const char *accept)
  97. {
  98.   const char *p;
  99.   const char *a;
  100.   size_t count = 0;
  101.  
  102.   for (p = s; *p != '\0'; ++p)
  103.     {
  104.       for (a = accept; *a != '\0'; ++a)
  105.         if (*p == *a)
  106.           break;
  107.       if (*a == '\0')
  108.         return count;
  109.       else
  110.         ++count;
  111.     }
  112.  
  113.   return count;
  114. }
  115.  
  116. #define __HAVE_ARCH_STRTOK
  117. extern inline char * strtok(char * s,const char * ct)
  118. {
  119.   char *sbegin, *send;
  120.   
  121.   sbegin  = s ? s : ___strtok;
  122.   if (!sbegin) {
  123.       return NULL;
  124.   }
  125.   sbegin += strspn(sbegin,ct);
  126.   if (*sbegin == '\0') {
  127.     ___strtok = NULL;
  128.     return( NULL );
  129.   }
  130.   send = strpbrk( sbegin, ct);
  131.   if (send && *send != '\0')
  132.     *send++ = '\0';
  133.   ___strtok = send;
  134.   return (sbegin);
  135. }
  136.  
  137. /* strstr !! */
  138.  
  139. #define __HAVE_ARCH_STRLEN
  140. extern inline size_t strlen(const char * s)
  141. {
  142.   const char *sc;
  143.   for (sc = s; *sc != '\0'; ++sc) ;
  144.   return(sc - s);
  145. }
  146.  
  147. /* strnlen !! */
  148.  
  149. #define __HAVE_ARCH_STRCMP
  150. extern inline int strcmp(const char * cs,const char * ct)
  151. {
  152.   char __res;
  153.  
  154.   __asm__
  155.        ("1:\tmoveb %0@+,%2\n\t" /* get *cs */
  156.         "cmpb %1@+,%2\n\t"      /* compare a byte */
  157.         "jne  2f\n\t"           /* not equal, break out */
  158.         "tstb %2\n\t"           /* at end of cs? */
  159.         "jne  1b\n\t"           /* no, keep going */
  160.         "jra  3f\n\t"        /* strings are equal */
  161.         "2:\tsubb %1@-,%2\n\t"  /* *cs - *ct */
  162.         "3:"
  163.         : "=a" (cs), "=a" (ct), "=d" (__res)
  164.         : "0" (cs), "1" (ct));
  165.   return __res;
  166. }
  167.  
  168. #define __HAVE_ARCH_STRNCMP
  169. extern inline int strncmp(const char * cs,const char * ct,size_t count)
  170. {
  171.   char __res;
  172.  
  173.   if (!count)
  174.     return 0;
  175.   __asm__
  176.        ("1:\tmovb %0@+,%3\n\t"          /* get *cs */
  177.         "cmpb   %1@+,%3\n\t"            /* compare a byte */
  178.         "jne    3f\n\t"                 /* not equal, break out */
  179.         "tstb   %3\n\t"                 /* at end of cs? */
  180.         "jeq    4f\n\t"                 /* yes, all done */
  181.         "subql  #1,%2\n\t"              /* no, adjust count */
  182.         "jne    1b\n\t"                 /* more to do, keep going */
  183.         "2:\tmoveq #0,%3\n\t"           /* strings are equal */
  184.         "jra    4f\n\t"
  185.         "3:\tsubb %1@-,%3\n\t"          /* *cs - *ct */
  186.         "4:"
  187.         : "=a" (cs), "=a" (ct), "=d" (count), "=d" (__res)
  188.         : "0" (cs), "1" (ct), "2" (count));
  189.   return __res;
  190. }
  191.  
  192. #define __HAVE_ARCH_MEMSET
  193. /*
  194.  * This is really ugly, but its highly optimizatiable by the
  195.  * compiler and is meant as compensation for gcc's missing
  196.  * __builtin_memset(). For the 680[23]0    it might be worth considering
  197.  * the optimal number of misaligned writes compared to the number of
  198.  * tests'n'branches needed to align the destination address. The
  199.  * 680[46]0 doesn't really care due to their copy-back caches.
  200.  *                        10/09/96 - Jes Sorensen
  201.  */
  202. extern inline void * __memset_g(void * s, int c, size_t count)
  203. {
  204.   void *xs = s;
  205.   size_t temp;
  206.  
  207.   if (!count)
  208.     return xs;
  209.  
  210.   c &= 0xff;
  211.   c |= c << 8;
  212.   c |= c << 16;
  213.  
  214.   if (count < 36){
  215.       long *ls = s;
  216.  
  217.       switch(count){
  218.       case 32: case 33: case 34: case 35:
  219.           *ls++ = c;
  220.       case 28: case 29: case 30: case 31:
  221.           *ls++ = c;
  222.       case 24: case 25: case 26: case 27:
  223.           *ls++ = c;
  224.       case 20: case 21: case 22: case 23:
  225.           *ls++ = c;
  226.       case 16: case 17: case 18: case 19:
  227.           *ls++ = c;
  228.       case 12: case 13: case 14: case 15:
  229.           *ls++ = c;
  230.       case 8: case 9: case 10: case 11:
  231.           *ls++ = c;
  232.       case 4: case 5: case 6: case 7:
  233.           *ls++ = c;
  234.           break;
  235.       default:
  236.           break;
  237.       }
  238.       s = ls;
  239.       if (count & 0x02){
  240.           short *ss = s;
  241.           *ss++ = c;
  242.           s = ss;
  243.       }
  244.       if (count & 0x01){
  245.           char *cs = s;
  246.           *cs++ = c;
  247.           s = cs;
  248.       }
  249.       return xs;
  250.   }
  251.  
  252.   if ((long) s & 1)
  253.     {
  254.       char *cs = s;
  255.       *cs++ = c;
  256.       s = cs;
  257.       count--;
  258.     }
  259.   if (count > 2 && (long) s & 2)
  260.     {
  261.       short *ss = s;
  262.       *ss++ = c;
  263.       s = ss;
  264.       count -= 2;
  265.     }
  266.   temp = count >> 2;
  267.   if (temp)
  268.     {
  269.       long *ls = s;
  270.       temp--;
  271.       do
  272.     *ls++ = c;
  273.       while (temp--);
  274.       s = ls;
  275.     }
  276.   if (count & 2)
  277.     {
  278.       short *ss = s;
  279.       *ss++ = c;
  280.       s = ss;
  281.     }
  282.   if (count & 1)
  283.     {
  284.       char *cs = s;
  285.       *cs = c;
  286.     }
  287.   return xs;
  288. }
  289.  
  290. /*
  291.  * __memset_page assumes that data is longword aligned. Most, if not
  292.  * all, of these page sized memsets are performed on page aligned
  293.  * areas, thus we do not need to check if the destination is longword
  294.  * aligned. Of course we suffer a serious performance loss if this is
  295.  * not the case but I think the risk of this ever happening is
  296.  * extremely small. We spend a lot of time clearing pages in
  297.  * get_empty_page() so I think it is worth it anyway. Besides, the
  298.  * 680[46]0 do not really care about misaligned writes due to their
  299.  * copy-back cache.
  300.  *
  301.  * The optimized case for the 680[46]0 is implemented using the move16
  302.  * instruction. My tests showed that this implementation is 35-45%
  303.  * faster than the original implementation using movel, the only
  304.  * caveat is that the destination address must be 16-byte aligned.
  305.  *                                            01/09/96 - Jes Sorensen
  306.  */
  307. extern inline void * __memset_page(void * s,int c,size_t count)
  308. {
  309.   unsigned long data, tmp;
  310.   void *xs, *sp;
  311.  
  312.   xs = sp = s;
  313.  
  314.   c = c & 255;
  315.   data = c | (c << 8);
  316.   data |= data << 16;
  317.  
  318. #ifdef CPU_M68040_OR_M68060_ONLY
  319.  
  320.   if (((unsigned long) s) & 0x0f)
  321.       memset(s, c, count);
  322.   else{
  323.       *((unsigned long *)(s))++ = data;
  324.       *((unsigned long *)(s))++ = data;
  325.       *((unsigned long *)(s))++ = data;
  326.       *((unsigned long *)(s))++ = data;
  327.  
  328.       __asm__ __volatile__("1:\t"
  329.                    ".chip 68040\n\t"
  330.                    "move16 %2@+,%0@+\n\t"
  331.                    ".chip 68k\n\t"
  332.                    "subqw  #8,%2\n\t"
  333.                    "subqw  #8,%2\n\t"
  334.                    "dbra   %1,1b\n\t"
  335.                    : "=a" (s), "=d" (tmp)
  336.                    : "a" (sp), "0" (s), "1" ((count - 16) / 16 - 1)
  337.                    );
  338.   }
  339.  
  340. #else
  341.   __asm__ __volatile__("1:\t"
  342.                "movel %2,%0@+\n\t"
  343.                "movel %2,%0@+\n\t"
  344.                "movel %2,%0@+\n\t"
  345.                "movel %2,%0@+\n\t"
  346.                "movel %2,%0@+\n\t"
  347.                "movel %2,%0@+\n\t"
  348.                "movel %2,%0@+\n\t"
  349.                "movel %2,%0@+\n\t"
  350.                "dbra  %1,1b\n\t"
  351.                : "=a" (s), "=d" (tmp)
  352.                : "d" (data), "0" (s), "1" (count / 32 - 1)
  353.                );
  354. #endif
  355.  
  356.   return xs;
  357. }
  358.  
  359. #define __memset_const(s,c,count) \
  360. ((count==PAGE_SIZE) ? \
  361.   __memset_page((s),(c),(count)) : \
  362.   __memset_g((s),(c),(count)))
  363.  
  364. #define memset(s, c, count) \
  365. (__builtin_constant_p(count) ? \
  366.  __memset_const((s),(c),(count)) : \
  367.  memset((s),(c),(count)))
  368.  
  369. #define __HAVE_ARCH_MEMCPY
  370. /*
  371.  * __builtin_memcpy() does not handle page-sized memcpys very well,
  372.  * thus following the same assumptions as for page-sized memsets, this
  373.  * function copies page-sized areas using an unrolled loop, without
  374.  * considering alignment.
  375.  *
  376.  * For the 680[46]0 only kernels we use the move16 instruction instead
  377.  * as it writes through the data-cache, invalidating the cache-lines
  378.  * touched. In this way we do not use up the entire data-cache (well,
  379.  * half of it on the 68060) by copying a page. An unrolled loop of two
  380.  * move16 instructions seem to the fastest. The only caveat is that
  381.  * both source and destination must be 16-byte aligned, if not we fall
  382.  * back to the generic memcpy function.  - Jes
  383.  */
  384. extern inline void * __memcpy_page(void * to, const void * from, size_t count)
  385. {
  386.   unsigned long tmp;
  387.   void *xto = to;
  388.  
  389. #ifdef CPU_M68040_OR_M68060_ONLY
  390.  
  391.   if (((unsigned long) to | (unsigned long) from) & 0x0f)
  392.       return memcpy(to, from, count);
  393.  
  394.   __asm__ __volatile__("1:\t"
  395.                ".chip 68040\n\t"
  396.                "move16 %1@+,%0@+\n\t"
  397.                "move16 %1@+,%0@+\n\t"
  398.                ".chip 68k\n\t"
  399.                "dbra  %2,1b\n\t"
  400.                : "=a" (to), "=a" (from), "=d" (tmp)
  401.                : "0" (to), "1" (from) , "2" (count / 32 - 1)
  402.                );
  403. #else
  404.   __asm__ __volatile__("1:\t"
  405.                "movel %1@+,%0@+\n\t"
  406.                "movel %1@+,%0@+\n\t"
  407.                "movel %1@+,%0@+\n\t"
  408.                "movel %1@+,%0@+\n\t"
  409.                "movel %1@+,%0@+\n\t"
  410.                "movel %1@+,%0@+\n\t"
  411.                "movel %1@+,%0@+\n\t"
  412.                "movel %1@+,%0@+\n\t"
  413.                "dbra  %2,1b\n\t"
  414.                : "=a" (to), "=a" (from), "=d" (tmp)
  415.                : "0" (to), "1" (from) , "2" (count / 32 - 1)
  416.                );
  417. #endif
  418.   return xto;
  419. }
  420.  
  421. #define __memcpy_const(to, from, n) \
  422. ((n==PAGE_SIZE) ? \
  423.   __memcpy_page((to),(from),(n)) : \
  424.   __builtin_memcpy((to),(from),(n)))
  425.  
  426. #define memcpy(to, from, n) \
  427. (__builtin_constant_p(n) ? \
  428.  __memcpy_const((to),(from),(n)) : \
  429.  memcpy((to),(from),(n)))
  430.  
  431. #define __HAVE_ARCH_MEMMOVE
  432. extern inline void * memmove(void * dest,const void * src, size_t n)
  433. {
  434.   void *xdest = dest;
  435.   size_t temp;
  436.  
  437.   if (!n)
  438.     return xdest;
  439.  
  440.   if (dest < src)
  441.     {
  442.       if ((long) dest & 1)
  443.     {
  444.       char *cdest = dest;
  445.       const char *csrc = src;
  446.       *cdest++ = *csrc++;
  447.       dest = cdest;
  448.       src = csrc;
  449.       n--;
  450.     }
  451.       if (n > 2 && (long) dest & 2)
  452.     {
  453.       short *sdest = dest;
  454.       const short *ssrc = src;
  455.       *sdest++ = *ssrc++;
  456.       dest = sdest;
  457.       src = ssrc;
  458.       n -= 2;
  459.     }
  460.       temp = n >> 2;
  461.       if (temp)
  462.     {
  463.       long *ldest = dest;
  464.       const long *lsrc = src;
  465.       temp--;
  466.       do
  467.         *ldest++ = *lsrc++;
  468.       while (temp--);
  469.       dest = ldest;
  470.       src = lsrc;
  471.     }
  472.       if (n & 2)
  473.     {
  474.       short *sdest = dest;
  475.       const short *ssrc = src;
  476.       *sdest++ = *ssrc++;
  477.       dest = sdest;
  478.       src = ssrc;
  479.     }
  480.       if (n & 1)
  481.     {
  482.       char *cdest = dest;
  483.       const char *csrc = src;
  484.       *cdest = *csrc;
  485.     }
  486.     }
  487.   else
  488.     {
  489.       dest = (char *) dest + n;
  490.       src = (const char *) src + n;
  491.       if ((long) dest & 1)
  492.     {
  493.       char *cdest = dest;
  494.       const char *csrc = src;
  495.       *--cdest = *--csrc;
  496.       dest = cdest;
  497.       src = csrc;
  498.       n--;
  499.     }
  500.       if (n > 2 && (long) dest & 2)
  501.     {
  502.       short *sdest = dest;
  503.       const short *ssrc = src;
  504.       *--sdest = *--ssrc;
  505.       dest = sdest;
  506.       src = ssrc;
  507.       n -= 2;
  508.     }
  509.       temp = n >> 2;
  510.       if (temp)
  511.     {
  512.       long *ldest = dest;
  513.       const long *lsrc = src;
  514.       temp--;
  515.       do
  516.         *--ldest = *--lsrc;
  517.       while (temp--);
  518.       dest = ldest;
  519.       src = lsrc;
  520.     }
  521.       if (n & 2)
  522.     {
  523.       short *sdest = dest;
  524.       const short *ssrc = src;
  525.       *--sdest = *--ssrc;
  526.       dest = sdest;
  527.       src = ssrc;
  528.     }
  529.       if (n & 1)
  530.     {
  531.       char *cdest = dest;
  532.       const char *csrc = src;
  533.       *--cdest = *--csrc;
  534.     }
  535.     }
  536.   return xdest;
  537. }
  538.  
  539. #define __HAVE_ARCH_MEMCMP
  540. #define memcmp(cs, ct, n) \
  541. (__builtin_constant_p(n) ? \
  542.  __builtin_memcmp((cs),(ct),(n)) : \
  543.  memcmp((cs),(ct),(n)))
  544.  
  545. #endif /* _M68K_STRING_H_ */
  546.